package com.css.casualties.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.UUID;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.css.casualties.entity.*;
import com.css.casualties.mapper.CasualtiesMapper;
import com.css.casualties.mapper.pop.service.PopService;
import com.css.casualties.service.*;
import com.css.config.QueueConfig;
import com.css.config.ThreadPoolConfig;
import com.css.economy.evaluate.entity.EconomyBuildingPriceEco;
import com.css.economy.evaluate.service.EconomyBuildingPriceService;
import com.css.economy.evaluate.service.EconomyEvaluateService;
import com.css.entity.*;
import com.css.influence.entity.EarthQuake;
import com.css.influence.entity.MessageLog.service.MessageLogService;
import com.css.influence.entity.SettingSeismicInfluenceflied;
import com.css.influence.mapper.SettingInfluenceMapper;
import com.css.influence.service.EarthQuakeInfluenceService;
import com.css.influence.service.InfluenceService;
import com.css.influence.vo.ToEvaluateVO;
import com.css.landslide.risk.param.LandslideParam;
import com.css.landslide.risk.service.LandslideRiskService;
import com.css.lossHouse.service.LossHouseService;
import com.css.mapper.DistrictBoundaryProvinceMapper;
import com.css.service.*;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.jdbc.UncategorizedSQLException;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author Dbj
 * @date 2024年09月18日  10:21
 * 人员伤亡评估计算
 */
@Service
@Slf4j
public class CasualtiesServiceImpl extends ServiceImpl<CasualtiesMapper,Casulaties> implements CasualtiesService {

    @Resource
    RyswModelService1 ryswModelService1;
    @Resource
    RyswModelService2 ryswModelService2;
    @Resource
    RyswModelService4 ryswModelService4;
    @Resource
    RyswModelService5 ryswModelService5;
    @Resource
    PopService popService;
    @Resource
    RyswModel3DataService ryswModel3DataService;

    @Resource
    RyswModel4DataService ryswModel4DataService;
    @Resource
    EconomyBuildingPriceService economyBuildingPriceService;


    ThreadPoolExecutor executor = ThreadPoolConfig.exeBizThreadPoolExecutor;

    //失败重试次数
    @Value("${spring.rabbitmq.failedRetry}")
    private Integer failedRetry;

    @Resource
    DataHouseDancengService dataHouseDancengService;
    @Resource
    DataHouseQitaService dataHouseQitaService;
    @Resource
    DataHouseRebarService dataHouseRebarService;
    @Resource
    DataHouseRebarRasterService dataHouseRebarRasterService;
    @Resource
    DataHouseBrickworkService dataHouseBrickworkService;
    @Resource
    GridDestoryDetailsService gridDestoryDetailsService;
    @Resource
    EconomyBuildingPriceEcoService economyBuildingPriceEcoService;
    @Resource
    RyswModelService ryswModelService;
    @Resource
    RabbitTemplate rabbitTemplate;

    @Resource
    MessageLogService messageLogService ;
    @Resource
    InfluenceYsxService influenceYsxService;
    @Resource
    SettingInfluenceMapper settingInfluenceMapper;
    @Resource
    EarthQuakeInfluenceService earthQuakeInfluenceService;
    @Resource
    EconomyEvaluateService economyEvaluateService;
    @Resource
    LossHouseService lossHouseService;
    @Resource
    LandslideRiskService landslideRiskService;
    @Resource
    InfluenceService influenceService;
    @Resource
    DistrictBoundaryProvinceMapper districtBoundaryProvinceMapper;
    private static final Map<String, Integer> retryMap = new ConcurrentHashMap<>();

    private void sendMsgToLandslide(String dataSourceKey, String id, String version) {
        Map<String,Object> toLandslideMap = new HashMap<>();
        toLandslideMap.put("influenceVersion",version);
        toLandslideMap.put("dataSourceKey",dataSourceKey);
        toLandslideMap.put("earthQuakeId",id);
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_LANDSLIDE,toLandslideMap);
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_LANDSLIDE,toLandslideMap);
                    flag = true;
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toLandslideMap), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_LANDSLIDE,status, content,"影响场发送消息给滑坡评估","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    //获取影响场是否跨省
    public List<DistrictBoundaryProvinceEntity> getProvinceByGeom(String geom){
        return districtBoundaryProvinceMapper.getIntersectProvince(geom);
    }

    private void getAndSetSum(Integer modelType,Map<Integer,Casulaties> table,Casulaties casulaties){
        if(table.containsKey(modelType)){
            Casulaties result = table.get(modelType);
            result.setInjureNum(result.getInjureNum().add(casulaties.getInjureNum()));
            result.setDeathNum(result.getDeathNum().add(casulaties.getDeathNum()));
            table.put(modelType,result);
        }else{
            table.put(modelType,casulaties);
        }
    }

    private double getPopNumBak(String geom){
        //影响场和省相交的那部分空间数据再和人口格网相交取值
        List<DataPop> dataPop  = popService.getBaseMapper().getByGeom(geom, "4490");
        if(ObjectUtils.isEmpty(dataPop) && !"province_root".equals(DynamicDataSourceContextHolder.peek())){
            //省级没查询到人口格网数据 就去查询国家专库的
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("province_root");
            dataPop = popService.getBaseMapper().getByGeom(geom, "4490");
        }
        //每个烈度圈的人口数  如果国家和省的人口数据都查询不到做0处理
        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
    }

    private double getPopNum(String geom){
        //影响场和省相交的那部分空间数据再和人口格网相交取值
        DataPop dataPop  = popService.getBaseMapper().getByGeom1(geom, "4490");
        if(ObjectUtils.isEmpty(dataPop) && !"province_root".equals(DynamicDataSourceContextHolder.peek())){
            //省级没查询到人口格网数据 就去查询国家专库的
            DynamicDataSourceContextHolder.clear();
            DynamicDataSourceContextHolder.push("province_root");
            dataPop = popService.getBaseMapper().getByGeom1(geom, "4490");
        }
        //每个烈度圈的人口数  如果国家和省的人口数据都查询不到做0处理
        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.getPopulation();
//        return ObjectUtils.isEmpty(dataPop)?0.0:dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
    }

    /**
     * 监听从影响场发送过来的消息 用于人员伤亡的
     */
    @RabbitListener(queues={QueueConfig.QUEUE_INFLUENCE_TO_EVALUATE_CASUALTIES}, ackMode = "MANUAL")
    @RabbitHandler
    @DSTransactional
    public void evaluate(Channel channel, Message message, ToEvaluateVO vo) throws IOException {
        CompletableFuture completableFuture = CompletableFuture.runAsync(()->{
            try {
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            } catch (IOException e) {
                e.printStackTrace();
            }
            String dataSourceKey = vo.getDataSource();
            //地震事件id
            String earthQuakeId = vo.getEarthQuakeId();
            //地震类型
            Integer earthType = vo.getEarthType();
            //地震类型
            Boolean publish = vo.getPublish();
            //影响场版本
            Date influenceVersion = vo.getInfluenceVersion();
            //发送消息给地震滑坡评估计算
            if(influenceVersion != null){
                sendMsgToLandslide(dataSourceKey,earthQuakeId,DateUtil.format(influenceVersion,"yyyy-MM-dd HH:mm:ss"));
            }
            log.info("人员伤亡开始计算");
            log.error("地震id"+vo.getEarthQuakeId()+"-- 评估人员伤亡"+"|| 开始。>> 参数:"+JSON.toJSONString(vo));
            // 切换到省份数据源
            DynamicDataSourceContextHolder.push(dataSourceKey);
            //影响场烈度和对应空间数据集合
            List<ToEvaluateVO.Influence> influenceList = vo.getInfluenceList();
            try {
                List<Casulaties> allList = new ArrayList<>();
                if(influenceList.size()>0 && influenceVersion!=null) {
                    Map<Integer, ToEvaluateVO.Influence> intensityMap = influenceList.stream().collect(Collectors.toMap(ToEvaluateVO.Influence::getIntensity, Function.identity()));
                    //实际影响场的最大烈度
                    int maxIntensity = influenceList.stream().mapToInt(ToEvaluateVO.Influence::getIntensity).max().getAsInt();
                    //时间因子
                    BigDecimal timeRatio = getTimeRatio(maxIntensity, vo.getEarthQuakeTime());
                    if(timeRatio==null){
                        //时间因子是非必填项当为空时自定义取值为1，方便后续的计算不报空指针
                        timeRatio = BigDecimal.ONE;
                    }
                    BigDecimal finalTimeRatio = timeRatio;

                    CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(()->{
                        //相同线程是可以获取数据源的，但是异步不可以，需要重新设置
                        System.out.println("线程1开始执行了");
                        try{
                            DynamicDataSourceContextHolder.push(dataSourceKey);
                            //查询震中位置所在省的模型1和模型2的数据 模型数据使用的是震级所在的省的数据
                            RyswModel1 model1 = ryswModelService1.getOne(null);
                            RyswModel2 model2 = ryswModelService2.getOne(null);
                            //影响场最外圈默认跨省
                            boolean flag = true;
                            //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                            for(int i=6;i<=maxIntensity;i++){
                                Map<Integer,Casulaties> casMap = new HashMap<>();
                                ToEvaluateVO.Influence influence = intensityMap.get(i);
                                if(ObjectUtils.isNotEmpty(influence)) {
                                    //Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
                                    //生成的影响场可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的人口数据数据，如果跨到的那个省的人口
                                    //数据不存在我们计算所需要的数据就用国家的人口数据
                                    List<DistrictBoundaryProvinceEntity> provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag,influence);
                                    //provinces>1表示跨省了
                                    double totalPopNum = 0.0;
                                    for (DistrictBoundaryProvinceEntity province : provinces) {
                                        //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                                        DynamicDataSourceContextHolder.clear();
                                        DynamicDataSourceContextHolder.push("province_"+province.getCode());
                                        //每个烈度圈的人口数
                                        double population =  getPopNum(province.getIntersectGeom());
                                        totalPopNum+=population;
                                    }
                                    //ρ为人口密度，人口密度=该烈度下人口总数/该烈度下影响场面积 用于模型2计算
                                    BigDecimal p = BigDecimal.ZERO;
                                    if(influence.getArea()>0.001){
                                        p = BigDecimal.valueOf(totalPopNum).divide(BigDecimal.valueOf(influence.getArea()),8, RoundingMode.HALF_DOWN);
                                    }
                                    //使用模型1计算人员伤亡
                                    //获取死亡率RJ  RJ是i烈度下的死亡率
                                    BigDecimal rj = getModel1Rj(model1, i);
                                    //死亡人数
                                    BigDecimal deadNum = BigDecimal.valueOf(totalPopNum).multiply(rj).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                    //受伤与死亡比例
                                    BigDecimal ratio = model1.getRatio();
                                    //受伤人数
                                    BigDecimal injureNum = deadNum.multiply(ratio).setScale(0,RoundingMode.HALF_DOWN);;
                                    Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum, injureNum, influenceVersion, 1);
                                    getAndSetSum(1,casMap,casulaties1);
                                    //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum,injureNum,influenceVersion,1));
                                    //使用模型2计算人员伤亡
                                    BigDecimal rj2 = getModel2Rj(model2, i,p);
                                    //死亡人数
                                    BigDecimal deadNum2 = BigDecimal.valueOf(totalPopNum).multiply(rj2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                    //受伤与死亡比例
                                    BigDecimal ratio2 = model2.getRatio();
                                    //受伤人数
                                    BigDecimal injureNum2 = deadNum2.multiply(ratio2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);
                                    Casulaties casulaties2 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum2, injureNum2, influenceVersion, 2);
                                    //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum2,injureNum2,influenceVersion,2));
                                    getAndSetSum(2,casMap,casulaties2);
                                    if(provinces.size() == 1){
                                        //不跨省  外圈不跨省那内圈肯定也不跨省就直接省去相交查询
                                        flag = false;
                                    }
                                }
                                Collection<Casulaties> values = casMap.values();
                                if(values.size()>0){
//                                list.addAll(values);
                                    allList.addAll(values);
                                }
                            }
//                        if(list.size()>0){
//                            //人员伤亡的计算结果需要保存在对应的专库中
//                            DynamicDataSourceContextHolder.clear();
//                            DynamicDataSourceContextHolder.push(dataSourceKey);
//                            saveBatch(list);
//                        }
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            DynamicDataSourceContextHolder.clear();
                            System.out.println("线程1执行完成");
                        }
                        return 1;
                    },executor);
                    CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(()->{
                        //相同线程是可以获取数据源的，但是异步不可以，需要重新设置
                        System.out.println("线程2开始执行了");
                        try{
                            DynamicDataSourceContextHolder.push(dataSourceKey);
                            //影响场最外圈默认跨省
                            boolean flag = true;
                            //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                            //List<Casulaties> casList = new ArrayList<>();
                            //兼容方法查询参数创建的临时对象
                            ToEvaluateVO.Influence influenceTemp = new ToEvaluateVO.Influence();
                            for(int i=6;i<=maxIntensity;i++){
                                ToEvaluateVO.Influence influence = intensityMap.get(i);
                                String intensity = getIntensityMap().get(i);
                                if(ObjectUtils.isNotEmpty(influence)) {
                                    //Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
                                    //获取指定烈度的伤亡率
                                    List<RyswModel3Data> ryswModel3Data = ryswModel3DataService.getDataByGeom(intensity,influence.getGeom());
                                    if(ObjectUtils.isEmpty(ryswModel3Data) || ryswModel3Data.size()==0){
                                        continue;
                                    }

                                    BigDecimal totalDeathNum = BigDecimal.ZERO;
                                    BigDecimal totalInjureNum = BigDecimal.ZERO;
                                    for (RyswModel3Data ryswModel3Datum : ryswModel3Data) {
                                        influenceTemp.setGeom(ryswModel3Datum.getGeomText());
                                        //上传的伤亡率和烈度数据可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的人口数据数据，如果跨到的那个省的人口
                                        //数据不存在我们计算所需要的数据就用国家的人口数据
                                        List<DistrictBoundaryProvinceEntity> provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag,influenceTemp);
                                        for (DistrictBoundaryProvinceEntity province : provinces) {
                                            //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                                            DynamicDataSourceContextHolder.clear();
                                            DynamicDataSourceContextHolder.push("province_"+province.getCode());
                                            //每个烈度圈的人口数
                                            double population =  getPopNum(province.getIntersectGeom());
                                            BigDecimal deadRatio = ryswModel3Datum.getDeadRatio();
                                            BigDecimal deathNum3 = BigDecimal.valueOf(population).multiply(deadRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                            totalDeathNum= totalDeathNum.add(deathNum3);
                                            BigDecimal injureRatio = ryswModel3Datum.getInjureRatio();
                                            BigDecimal injureNum3 = BigDecimal.valueOf(population).multiply(injureRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                            totalInjureNum = totalInjureNum.add(injureNum3);
                                        }
                                    }
                                    Casulaties casulaties3 = buildCasulaties(earthQuakeId, i, influence.getGeom(), totalDeathNum, totalInjureNum, influenceVersion, 3);
                                    //casList.add(casulaties3);
                                    allList.add(casulaties3);
                                }
                            }
//                        if(casList.size()>0){
//                            //人员伤亡的计算结果需要保存在对应的专库中
//                            DynamicDataSourceContextHolder.clear();
//                            DynamicDataSourceContextHolder.push(dataSourceKey);
//                            saveBatch(casList);
//                        }
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            DynamicDataSourceContextHolder.clear();
                            System.out.println("线程2执行完成");
                        }
                        return 1;
                    },executor);
                    BigDecimal finalTimeRatio1 = timeRatio;
                    CompletableFuture completableFuture3 = CompletableFuture.supplyAsync(()->{
                        System.out.println("线程3开始执行了");
                        try{
                            DynamicDataSourceContextHolder.push(dataSourceKey);
                            List<Casulaties> list1 = new ArrayList<>();
                            //List<GridDestoryDetails> destoryList = new ArrayList<>();
                            List<EconomyBuildingPriceEco> finalList = new ArrayList<>();
                            //查询模型4的信息  模型数据使用的是震级所在的省的数据
                            RyswModel4 model4 = ryswModelService4.getOne(null);
                            //查询模型5 不同破坏程度下的伤亡率 模型数据使用的是震级所在的省的数据
                            List<RyswModel5> model5List = ryswModelService5.list(null);
                            Map<String, List<RyswModel5>> model5Map = new HashMap<>();
                            if(ObjectUtils.isNotEmpty(model5List) && model5List.size()>0){
                                //按照破坏程度分组
                                model5Map = model5List.stream().collect(Collectors.groupingBy(RyswModel5::getDamageLevel));
                            }
                            //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                            List<InfluenceYsx> influenceYsxList = new ArrayList<>();
                            //影响场最外圈默认跨省
                            boolean flag = true;
                            for(int i=6;i<=maxIntensity;i++){
                                ToEvaluateVO.Influence influence = intensityMap.get(i);
                                if(ObjectUtils.isNotEmpty(influence)){
                                    //根据影响场烈度的空间数据查询易损性数据 模型数据使用的是震级所在的省的数据
                                    List<RyswModel4Data> ryswModel4DataList = ryswModel4DataService.getIntersectYsx(influence.getGeom(), influence.getCode(),getIntensityMap().get(i));
                                    //生成的影响场可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的数据，如果跨到的那个省的
                                    //数据不存在我们计算所需要的数据就用国家的数据
                                    //provinces>1表示跨省了
                                    List<DistrictBoundaryProvinceEntity> provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag,  influence);
                                    if(provinces.size() == 1){
                                        //不跨省  外圈不跨省那内圈肯定也不跨省就直接省去相交查询
                                        flag = false;
                                    }
                                    //影响场和易损性相交获取不同烈度下的易损性信息
                                    if(ObjectUtils.isNotEmpty(ryswModel4DataList) && ryswModel4DataList.size()>0){
                                        // 一个烈度圈可能与多个易损性数据相交7烈度的一半圈和一批易损性相交，另外半圈可能和另外的一批易损性数据相交
                                        Map<String, List<RyswModel4Data>> pidMap = ryswModel4DataList.stream().collect(Collectors.groupingBy(RyswModel4Data::getIntersectGeom));
                                        Iterator<Map.Entry<String, List<RyswModel4Data>>> iterator = pidMap.entrySet().iterator();
                                        while (iterator.hasNext()){
                                            Map.Entry<String, List<RyswModel4Data>> next = iterator.next();
                                            List<RyswModel4Data> v = next.getValue();
                                            //影响场烈度圈和易损性数据相交部分的空间数据
                                            String geom = v.get(0).getIntersectGeom();
                                            Map<Integer,Casulaties> casMap = new HashMap<>();
                                            Map<Integer,Casulaties> casMap2 = new HashMap<>();
                                            //例 如果地震震中位置所在省的影响场部分与两个易损性数据相交了得到u和b，且影响场又延伸到了外省，先求得外省部分的人口，然后分别用外省
                                            //的人口分别和两个易损性数据参与计算得到两个伤亡值，然后用u和b分别得到各自区域内的人口数据参与计算得到两个值，然后4个值根据关联的条件进行整合相加
                                            //形成两个易损性区域内的人员伤亡值
                                            //影响场与易损性数据相交部分的人口数 = 影响场与易损性数据相交部分的人口数+影响场和外省相交部分的人口数据（如果存在外省的话）
                                            BigDecimal totalPopNum = BigDecimal.ZERO;
                                            //用别省的人口和地震震中位置所在省的模型信息计算人员伤亡
                                            for (DistrictBoundaryProvinceEntity province : provinces) {
                                                //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                                                DynamicDataSourceContextHolder.clear();
                                                DynamicDataSourceContextHolder.push("province_"+province.getCode());
                                                //人口p
                                                double popNum = 0;
                                                if(!flag){
                                                    //不管跨没跨省只要是震中位置所在省，则需要使用影响场先和易损性相交geom，则使用相交的geom再和人口格网相交获取人口数
                                                    popNum = getPopNum(geom);
                                                }else{
                                                    //如果跨省了，那么查询跨省部分的空间数据与跨省人口格网的人口数据
                                                    popNum = getPopNum(province.getIntersectGeom());
                                                }
                                                totalPopNum = totalPopNum.add(BigDecimal.valueOf(ObjectUtils.isEmpty(popNum)?0.0:popNum));

                                            }
                                            //计算模型4的算法  模型5需要模型4的易损性数据，需要在一个逻辑实现
                                            Casulaties casulaties = mathModel4(earthQuakeId, influenceVersion, v, model4, i, geom,  finalList, totalPopNum.doubleValue(), null);
                                            getAndSetSum(4,casMap,casulaties);
                                            list1.addAll(casMap.values());
                                            //计算人员伤亡模型5算法
                                            //易损性存在不同的建筑物类别
                                            BigDecimal deathNumTotal = BigDecimal.ZERO;
                                            BigDecimal injureNumTotal = BigDecimal.ZERO;
                                            for (RyswModel4Data ryswModel4Data : v) {
                                                BigDecimal basic = ryswModel4Data.getBasic();
                                                List<RyswModel5> ryswModel51 = model5Map.get("1");
                                                if(ObjectUtils.isNotEmpty(ryswModel51) && ryswModel51.size()>0){
                                                    //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                                    BigDecimal deathNum = basic.multiply(ryswModel51.get(0).getDeadRatio()).multiply(totalPopNum);
                                                    BigDecimal injureNum = basic.multiply(ryswModel51.get(0).getInjureRatio()).multiply(totalPopNum);
                                                    deathNumTotal = deathNumTotal.add(deathNum);
                                                    injureNumTotal = injureNumTotal.add(injureNum);
                                                }
                                                BigDecimal slight = ryswModel4Data.getSlight();
                                                List<RyswModel5> ryswModel52 = model5Map.get("2");
                                                if(ObjectUtils.isNotEmpty(ryswModel52) && ryswModel52.size()>0){
                                                    //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                                    BigDecimal deathNum = slight.multiply(ryswModel52.get(0).getDeadRatio()).multiply(totalPopNum);
                                                    BigDecimal injureNum = slight.multiply(ryswModel52.get(0).getInjureRatio()).multiply(totalPopNum);
                                                    deathNumTotal = deathNumTotal.add(deathNum);
                                                    injureNumTotal = injureNumTotal.add(injureNum);
                                                }
                                                BigDecimal mid = ryswModel4Data.getMid();
                                                List<RyswModel5> ryswModel53 = model5Map.get("3");
                                                if(ObjectUtils.isNotEmpty(ryswModel53) && ryswModel53.size()>0){
                                                    //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                                    BigDecimal deathNum = mid.multiply(ryswModel53.get(0).getDeadRatio()).multiply(totalPopNum);
                                                    BigDecimal injureNum = mid.multiply(ryswModel53.get(0).getInjureRatio()).multiply(totalPopNum);
                                                    deathNumTotal = deathNumTotal.add(deathNum);
                                                    injureNumTotal = injureNumTotal.add(injureNum);
                                                }
                                                BigDecimal serious = ryswModel4Data.getSerious();
                                                List<RyswModel5> ryswModel54 = model5Map.get("4");
                                                if(ObjectUtils.isNotEmpty(ryswModel54) && ryswModel54.size()>0){
                                                    //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                                    BigDecimal deathNum = serious.multiply(ryswModel54.get(0).getDeadRatio()).multiply(totalPopNum);
                                                    BigDecimal injureNum = serious.multiply(ryswModel54.get(0).getInjureRatio()).multiply(totalPopNum);
                                                    deathNumTotal = deathNumTotal.add(deathNum);
                                                    injureNumTotal = injureNumTotal.add(injureNum);
                                                }
                                                BigDecimal destory = ryswModel4Data.getDestory();
                                                List<RyswModel5> ryswModel55 = model5Map.get("5");
                                                if(ObjectUtils.isNotEmpty(ryswModel55) && ryswModel55.size()>0){
                                                    //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                                    BigDecimal deathNum = destory.multiply(ryswModel55.get(0).getDeadRatio()).multiply(totalPopNum);
                                                    BigDecimal injureNum = destory.multiply(ryswModel55.get(0).getInjureRatio()).multiply(totalPopNum);
                                                    deathNumTotal = deathNumTotal.add(deathNum);
                                                    injureNumTotal = injureNumTotal.add(injureNum);
                                                }
                                                //保存易损性中间结果用于其他算法的评估
                                                InfluenceYsx influenceYsx = new InfluenceYsx();
                                                //String provinceCode = dataSourceKey.indexOf("_")>0?dataSourceKey.split("_")[1]:dataSourceKey;
                                                influenceYsx.setId(UUID.randomUUID().toString().replace("-","")).setEarthQuakeId(earthQuakeId)
                                                        .setInfluenceVersion(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(influenceVersion)).setIntensity(i+"").setGeom(geom).setPopNum(totalPopNum.doubleValue())
                                                        .setStructureType(ryswModel4Data.getStructureType()).setMid(ryswModel4Data.getMid()).setSerious(ryswModel4Data.getSerious())
                                                        .setDestory(ryswModel4Data.getDestory());
                                                influenceYsxList.add(influenceYsx);
                                            }
                                            deathNumTotal = deathNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
                                            injureNumTotal = injureNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
                                            Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, geom, deathNumTotal, injureNumTotal, influenceVersion, 5);
                                            getAndSetSum(5,casMap2,casulaties1);
                                            list1.addAll(casMap2.values());
//                                    //易损性存在不同的建筑物类别
//                                    BigDecimal deathNumTotal = BigDecimal.ZERO;
//                                    BigDecimal injureNumTotal = BigDecimal.ZERO;
//                                    for (RyswModel4Data ryswModel4Data : v) {
//                                        BigDecimal basic = ryswModel4Data.getBasic();
//                                        List<RyswModel5> ryswModel51 = model5Map.get("1");
//                                        if(ObjectUtils.isNotEmpty(ryswModel51) && ryswModel51.size()>0){
//                                            //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                            BigDecimal deathNum = basic.multiply(ryswModel51.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            BigDecimal injureNum = basic.multiply(ryswModel51.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            deathNumTotal = deathNumTotal.add(deathNum);
//                                            injureNumTotal = injureNumTotal.add(injureNum);
//                                        }
//                                        BigDecimal slight = ryswModel4Data.getSlight();
//                                        List<RyswModel5> ryswModel52 = model5Map.get("2");
//                                        if(ObjectUtils.isNotEmpty(ryswModel52) && ryswModel52.size()>0){
//                                            //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                            BigDecimal deathNum = slight.multiply(ryswModel52.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            BigDecimal injureNum = slight.multiply(ryswModel52.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            deathNumTotal = deathNumTotal.add(deathNum);
//                                            injureNumTotal = injureNumTotal.add(injureNum);
//                                        }
//                                        BigDecimal mid = ryswModel4Data.getMid();
//                                        List<RyswModel5> ryswModel53 = model5Map.get("3");
//                                        if(ObjectUtils.isNotEmpty(ryswModel53) && ryswModel53.size()>0){
//                                            //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                            BigDecimal deathNum = mid.multiply(ryswModel53.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            BigDecimal injureNum = mid.multiply(ryswModel53.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            deathNumTotal = deathNumTotal.add(deathNum);
//                                            injureNumTotal = injureNumTotal.add(injureNum);
//                                        }
//                                        BigDecimal serious = ryswModel4Data.getSerious();
//                                        List<RyswModel5> ryswModel54 = model5Map.get("4");
//                                        if(ObjectUtils.isNotEmpty(ryswModel54) && ryswModel54.size()>0){
//                                            //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                            BigDecimal deathNum = serious.multiply(ryswModel54.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            BigDecimal injureNum = serious.multiply(ryswModel54.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            deathNumTotal = deathNumTotal.add(deathNum);
//                                            injureNumTotal = injureNumTotal.add(injureNum);
//                                        }
//                                        BigDecimal destory = ryswModel4Data.getDestory();
//                                        List<RyswModel5> ryswModel55 = model5Map.get("5");
//                                        if(ObjectUtils.isNotEmpty(ryswModel55) && ryswModel55.size()>0){
//                                            //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                            BigDecimal deathNum = destory.multiply(ryswModel55.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            BigDecimal injureNum = destory.multiply(ryswModel55.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                            deathNumTotal = deathNumTotal.add(deathNum);
//                                            injureNumTotal = injureNumTotal.add(injureNum);
//                                        }
//                                    }
//                                    deathNumTotal = deathNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);;
//                                    injureNumTotal = injureNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);;
//                                    list1.add(buildCasulaties(earthQuakeId,i,geom,deathNumTotal,injureNumTotal,influenceVersion,5));
                                        }
                                    }
                                }
                            }
                            //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                            DynamicDataSourceContextHolder.clear();
                            DynamicDataSourceContextHolder.push(dataSourceKey);
                            if(influenceYsxList.size()>0){
                                //记录影响场和易损性的相交后的信息用于后续的失去住所的评估计算
                                influenceYsxService.saveBatch(influenceYsxList);
                            }
                            if(list1.size()>0){
                                saveBatch(list1);
                            }
                            //用于经济损失建筑物结构经济损失
//                            if(destoryList.size()>0){
//                                gridDestoryDetailsService.saveBatch(destoryList);
//                            }
//                            if(finalList.size()>0){
//                                economyBuildingPriceEcoService.saveBatch(finalList);
//                            }
                        }catch (Exception e){
                            e.printStackTrace();
                        }finally {
                            DynamicDataSourceContextHolder.clear();
                        }
                        System.out.println("线程3执行完成");
                        return 2;
                    },executor);
                    CompletableFuture.allOf(completableFuture1,completableFuture2,completableFuture3).get();
                    if(allList.size()>0){
                        //人员伤亡的计算结果需要保存在对应的专库中
                        DynamicDataSourceContextHolder.clear();
                        DynamicDataSourceContextHolder.push(dataSourceKey);
                        saveBatch(allList);
                    }
                    System.out.println("执行完毕");
                    log.error("地震id"+vo.getEarthQuakeId()+"-- 评估人员伤亡"+"|| 成功。>> 参数:"+JSON.toJSONString(vo));
                    //向经济损失计算发送消息 进行经济损失的计算
                    sendMsgToEconomyEvaluate(vo);
                    //发送消息给失去住所评估
                    sendMsgToLossHouseEvaluate(earthQuakeId,dataSourceKey,influenceVersion,earthType,publish);
                }
            }catch (Exception e) {
                e.printStackTrace();
                log.error("{},---评估人员伤亡||失败,消息将被拒绝，>>参数:{}", earthQuakeId,JSON.toJSONString(vo));
//                int retryCount = retryMap.getOrDefault(earthQuakeId, 0);
//                log.error("{},--评估人员伤亡||失败,处理消息时发生错误:{},即将开始第{}次消息重试...", earthQuakeId,e.getMessage(),retryCount + 1, e);
//                if (retryCount >= failedRetry - 1) {
//                    log.error("{},---评估人员伤亡||失败,消息将被拒绝，>>参数:{}", earthQuakeId,JSON.toJSONString(vo));
//                    // 拒绝消息，并且不重新入队
//                    try {
//                        channel.basicReject(message.getMessageProperties().getDeliveryTag(), false);
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.remove(earthQuakeId);
//                } else {
//                    // 重新发送消息到队列
//                    try {
//                        channel.basicPublish(message.getMessageProperties().getReceivedExchange(),
//                                message.getMessageProperties().getReceivedRoutingKey(),
//                                MessageProperties.MINIMAL_PERSISTENT_BASIC,
//                                JSON.toJSONBytes(vo));
//                    } catch (IOException ex) {
//                        ex.printStackTrace();
//                    }
//                    retryMap.put(earthQuakeId, retryCount + 1);
//                    log.error("地震id"+vo.getEarthQuakeId()+"-- 评估人员伤亡"+"|| 失败。>> 参数:"+JSON.toJSONString(vo));
//                }
            } finally {
                DynamicDataSourceContextHolder.clear();
                log.info("人员伤亡计算完成");
            }
            //没有生成影响场也不需要进行人员伤亡的计算 但是因为报告的原因需要向经济损失发送消息
            if(influenceList.size()==0 || influenceVersion==null) {
                //向经济损失计算发送消息 进行经济损失的计算
//                sendMsgToEconomyEvaluate(earthQuakeId,dataSourceKey,influenceVersion,earthType,publish);
                sendMsgToEconomyEvaluate(vo);
                DynamicDataSourceContextHolder.clear();
                log.info("人员伤亡计算完成");
            }
        },executor);

    }

    private List<DistrictBoundaryProvinceEntity> getDistrictBoundaryProvinceEntities(String dataSourceKey, boolean flag, ToEvaluateVO.Influence influence) {
        List<DistrictBoundaryProvinceEntity> provinces = new ArrayList<>();
        if(dataSourceKey.contains("_root")){
            //国家直接查询自己的不存在跨不跨省之说
            DistrictBoundaryProvinceEntity districtBoundaryProvinceEntity = new DistrictBoundaryProvinceEntity();
            DynamicDataSourceContextHolder.clear();
            districtBoundaryProvinceEntity.setCode("root");
//            districtBoundaryProvinceEntity.setArea(BigDecimal.valueOf(influence.getArea()));
            districtBoundaryProvinceEntity.setIntersectGeom(influence.getGeom());
            provinces.add(districtBoundaryProvinceEntity);
        }else{
            if(flag){
                //默认跨省
                provinces = getProvinceByGeom(influence.getGeom());
            }else{
                //不跨省  手动构建数据  避免空间数据相交查询
                DistrictBoundaryProvinceEntity districtBoundaryProvinceEntity = new DistrictBoundaryProvinceEntity();
                DynamicDataSourceContextHolder.clear();
                String provinceCode = dataSourceKey.indexOf("_")>0?dataSourceKey.split("_")[1]:dataSourceKey;
                districtBoundaryProvinceEntity.setCode(provinceCode);
//                districtBoundaryProvinceEntity.setArea(BigDecimal.valueOf(influence.getArea()));
                districtBoundaryProvinceEntity.setIntersectGeom(influence.getGeom());
                provinces.add(districtBoundaryProvinceEntity);
            }
        }

        return provinces;
    }

    private void sendMsgToLossHouseEvaluate(String earthQuakeId, String dataSourceKey, Date influenceVersion,Integer earthType,Boolean publish) {
        Map<String,Object> map = new HashMap<>();
        map.put("earthQuakeId",earthQuakeId);
        map.put("dataSource",dataSourceKey);
        map.put("earthType",earthType);
        map.put("publish",publish);
        map.put("influenceVersion", JSON.toJSONStringWithDateFormat(influenceVersion,"yyyy-MM-dd HH:mm:ss"));
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_LOSSHOUSE,QueueConfig.KEY_CASULATIES_TO_LOSSHOUSE,map);
            log.error("地震id"+earthQuakeId+"-- 给失去住所发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_LOSSHOUSE,QueueConfig.KEY_CASULATIES_TO_LOSSHOUSE,map);
                    flag = true;
                    log.error("地震id"+earthQuakeId+"-- 给失去住所发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+earthQuakeId+"-- 给失去住所发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(map));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(map), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_CASULATIES_TO_LOSSHOUSE,QueueConfig.KEY_CASULATIES_TO_LOSSHOUSE,status, content,"人员伤亡发送消息给经济损失","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    private void sendMsgToEconomyEvaluate(ToEvaluateVO vo) {
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY, vo);
            log.error("地震id"+vo.getEarthQuakeId()+"-- 给经济损失发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(vo));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY,vo);
                    flag = true;
                    log.error("地震id"+vo.getEarthQuakeId()+"-- 给经济损失发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(vo));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+vo.getEarthQuakeId()+"-- 给经济损失发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(vo));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(vo), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY,status, content,"人员伤亡发送消息给经济损失","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }
    private void sendMsgToEconomyEvaluate1(String earthQuakeId,String dataSourceKey,Date influenceVersion,Integer earthType,Boolean publish) {
        Map<String,Object> map = new HashMap<>();
        map.put("earthQuakeId",earthQuakeId);
        map.put("dataSource",dataSourceKey);
        map.put("earthType",earthType);
        map.put("publish",publish);
        map.put("influenceVersion", JSON.toJSONStringWithDateFormat(influenceVersion,"yyyy-MM-dd HH:mm:ss"));

        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY,map);
            log.error("地震id"+earthQuakeId+"-- 给经济损失发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY,map);
                    flag = true;
                    log.error("地震id"+earthQuakeId+"-- 给经济损失发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(map));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+earthQuakeId+"-- 给经济损失发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(map));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(map), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_CASULATIES_TO_ECONOMY,QueueConfig.KEY_CASULATIES_TO_ECONOMY,status, content,"人员伤亡发送消息给经济损失","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }

    /**
     * 根据发震时间和影响场最大烈度获取时间因子
     */
    private BigDecimal getTimeRatio(int maxIntensity,Date earthQuakeTime) {
        //获取时间因子 如果维护了的话 则用时间因子计算最终的人员伤亡
        //判断发震时间是否在06:00~18:00之间 是则为白天时间因子为1  用计算的死亡人数和受伤人数去乘 时间因子1 因为白天时间因子固定是1 所以只考虑夜间的时间因子即可
        int hours = earthQuakeTime.getHours();
        BigDecimal timeRatio = BigDecimal.ONE;
        if(6>=hours || hours>=18){
            //获取夜间时间因子 根据影响场的最大烈度获取最大烈度的时间因子
            RyswModel ryswModel = ryswModelService.getOne(null);
            if(ObjectUtils.isNotEmpty(ryswModel)){
                switch (maxIntensity){
                    case 6:
                        timeRatio = ryswModel.getIntensity6();
                        break;
                    case 7:
                        timeRatio = ryswModel.getIntensity7();
                        break;
                    case 8:
                        timeRatio = ryswModel.getIntensity8();
                        break;
                    case 9:
                        timeRatio = ryswModel.getIntensity9();
                        break;
                    case 10:
                        timeRatio = ryswModel.getIntensity10();
                        break;
                    case 11:
                        timeRatio = ryswModel.getIntensity11();
                        break;
                    case 12:
                        timeRatio = ryswModel.getIntensity12();
                        break;
                    default:
                }
            }
        }
        return timeRatio;
    }
    /**
     * 计算模型4的算法
     */
    private Casulaties mathModel4(String earthQuakeId, Date influenceVersion, List<RyswModel4Data> v, RyswModel4 model4, int i,
//                            String geom,List<GridDestoryDetails> gridDestoryList,Double popNum,StringBuilder builder){
                                  String geom, List<EconomyBuildingPriceEco> finalList, Double popNum, StringBuilder builder){
        //各烈度下房屋的毁坏比
        BigDecimal destoryRatio = BigDecimal.ZERO;
        //该烈度下所有结构类型房屋总面积
        BigDecimal totalArea = BigDecimal.ZERO;
        //获取不同烈度下的所有结构类型总的毁坏面积
        BigDecimal totalDestoryArea = BigDecimal.ZERO;
        //List<GridDestoryDetails> gridDestoryDetailsList = new ArrayList<>();

        for (RyswModel4Data ryswModel4Data : v) {
//            GridDestoryDetails gridDestoryDetails = GridDestoryDetails.builder().id(UUID.randomUUID().toString().replace("-",""))
//                    .earthQuakeId(earthQuakeId).influenceVersion(influenceVersion).build();
            //影响场和易损性相交的部分
            String intensity = ryswModel4Data.getIntensity();
            BigDecimal area = BigDecimal.ZERO;
            if("1".equals(ryswModel4Data.getStructureType())){
                //钢混结构
                List<DataHouseRebar> rebarList = null;
                try{
                    rebarList = dataHouseRebarService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                }catch (UncategorizedSQLException e){
                    if("4490".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4326");
                        rebarList =  dataHouseRebarService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }else if("4326".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4490");
                        rebarList =  dataHouseRebarService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }
                }
                if(ObjectUtils.isNotEmpty(rebarList) && rebarList.size()>0){
                    //这个烈度圈内的所有钢混结构的总面积
                    area = rebarList.get(0).getHouse();
                    BigDecimal destoryArea = ryswModel4Data.getDestory().multiply(area);
                    //BigDecimal destoryArea = publicMethod(area,ryswModel4Data,"1",intensity,gridDestoryDetails);
                    totalDestoryArea = totalDestoryArea.add(destoryArea);
                }else{
                    builder.append("烈度").append(i).append("没有获取到多层钢筋混凝土房屋数据").append("、");
                }
            }
            if("2".equals(ryswModel4Data.getStructureType())){
                //多层砌体
                List<DataHouseBrickwork> bwList = null;
                try{
                    bwList = dataHouseBrickworkService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                }catch (UncategorizedSQLException e){
                    if("4490".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4326");
                        bwList =  dataHouseBrickworkService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }else if("4326".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4490");
                        bwList =  dataHouseBrickworkService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }
                }
                if(ObjectUtils.isNotEmpty(bwList) && bwList.size()>0){
                    //这个烈度圈内的所有钢混结构的总面积
                    area = bwList.get(0).getHouse();
                    BigDecimal destoryArea = ryswModel4Data.getDestory().multiply(area);
//                    BigDecimal destoryArea = publicMethod(area,ryswModel4Data,"2",intensity,gridDestoryDetails);
                    totalDestoryArea = totalDestoryArea.add(destoryArea);
                }else{
                    builder.append("烈度").append(i).append("没有获取到多层砌体房屋数据").append("、");
                }
            }
            if("3".equals(ryswModel4Data.getStructureType())){
                //单层
                List<DataHousedanceng> dancengList = null;
                try{
                    dancengList = dataHouseDancengService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                }catch (UncategorizedSQLException e){
                    if("4490".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4326");
                        dancengList =  dataHouseDancengService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }else if("4326".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4490");
                        dancengList =  dataHouseDancengService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }
                }

                if(ObjectUtils.isNotEmpty(dancengList) && dancengList.size()>0){
                    //这个烈度圈内的所有钢混结构的总面积
                    area = dancengList.get(0).getHouse();
                    BigDecimal destoryArea = ryswModel4Data.getDestory().multiply(area);
//                    BigDecimal destoryArea = publicMethod(area,ryswModel4Data,"3",intensity,gridDestoryDetails);
                    totalDestoryArea = totalDestoryArea.add(destoryArea);
                }else{
                    builder.append("烈度").append(i).append("没有获取到单层民宅数据").append("、");
                }
            }
            if("4".equals(ryswModel4Data.getStructureType())){
                //其他
                List<DataHouseQita> qitaList = null;
                try{
                    qitaList = dataHouseQitaService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                }catch (UncategorizedSQLException e){
                    if("4490".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4326");
                        qitaList =  dataHouseQitaService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }else if("4326".equals(ryswModel4Data.getCode())){
                        ryswModel4Data.setCode("4490");
                        qitaList =  dataHouseQitaService.getByGeom(ryswModel4Data.getIntersectGeom(),ryswModel4Data.getCode());
                    }
                }
                if(ObjectUtils.isNotEmpty(qitaList) && qitaList.size()>0){
                    //这个烈度圈内的所有钢混结构的总面积
                    area = qitaList.get(0).getHouse();
                    BigDecimal destoryArea = ryswModel4Data.getDestory().multiply(area);
//                    BigDecimal destoryArea = publicMethod(area,ryswModel4Data,"4",intensity,gridDestoryDetails);
                    totalDestoryArea = totalDestoryArea.add(destoryArea);
                }else{
                    builder.append("烈度").append(i).append("没有获取到其他房屋数据").append("、");
                }
            }
            totalArea = totalArea.add(area);
            //gridDestoryDetailsList.add(gridDestoryDetails);
        }
        if(totalArea.compareTo(BigDecimal.ZERO)!=0){
            destoryRatio = totalDestoryArea.divide(totalArea,8,RoundingMode.HALF_DOWN);
        }
        //利用毁坏比求死亡率rj
        BigDecimal param1 = model4.getParam1();
        BigDecimal param2 = model4.getParam2();
        double pow = Math.pow(destoryRatio.doubleValue(), 0.1);
        BigDecimal logR = param1.multiply(BigDecimal.valueOf(pow)).subtract(param2);
        BigDecimal rj = BigDecimal.valueOf(Math.pow(10, logR.doubleValue()));
        BigDecimal ND = rj.multiply(BigDecimal.valueOf(popNum)).setScale(0,RoundingMode.HALF_DOWN);
        //死亡人数
        BigDecimal ratio = model4.getRatio();
        BigDecimal injureNum = ND.multiply(ratio).setScale(0,RoundingMode.HALF_DOWN);
        //gridDestoryList.addAll(gridDestoryDetailsList);
        return buildCasulaties(earthQuakeId,i,geom,ND,injureNum,influenceVersion,4);

    }
    public BigDecimal publicMethod(BigDecimal area,RyswModel4Data ryswModel4Data,String type,String intensity,GridDestoryDetails gridDestoryDetails){
        //获取钢混结构在这个烈度下的不同破坏程度的面积
        //基本完好的
        BigDecimal basicArea = ryswModel4Data.getBasic().multiply(area);
        //轻微破坏的
        BigDecimal slightArea = ryswModel4Data.getSlight().multiply(area);
        //轻微破坏的
        BigDecimal midArea = ryswModel4Data.getMid().multiply(area);
        //轻微破坏的
        BigDecimal seriousArea = ryswModel4Data.getSerious().multiply(area);
        //轻微破坏的
        BigDecimal destoryArea = ryswModel4Data.getDestory().multiply(area);
        gridDestoryDetails.setStructureType(type);
        gridDestoryDetails.setIntensity(intensity);
        gridDestoryDetails.setBasicArea(basicArea);
        gridDestoryDetails.setSlightArea(slightArea);
        gridDestoryDetails.setMidArea(midArea);
        gridDestoryDetails.setSeriousArea(seriousArea);
        gridDestoryDetails.setDestoryArea(destoryArea);
        gridDestoryDetails.setGeom(ryswModel4Data.getIntersectGeom());
        return destoryArea;
    }
    private Map<Integer,String> getIntensityMap(){
        Map<Integer,String> map = new HashMap<>();
        map.put(6,"Ⅵ");
        map.put(7,"Ⅶ");
        map.put(8,"Ⅷ");
        map.put(9,"Ⅸ");
        map.put(10,"Ⅹ");
        map.put(11,"Ⅺ");
        map.put(12,"Ⅻ");
        return map;
    }
    //构建人员伤亡实体对象
    private Casulaties buildCasulaties(String earthQuakeId,Integer i,String geom,BigDecimal deadNum,BigDecimal injureNum,Date influenceVersion,Integer modelType){
        Casulaties casulaties = new Casulaties();
        casulaties.setId(UUID.randomUUID().toString().replace("-","")).setModelType(modelType).setVersion(influenceVersion)
                .setEarthQuakeId(earthQuakeId).setIntensity(i).setGeom(geom).setDeathNum(deadNum).setInjureNum(injureNum).setCreateTime(DateUtil.date());
        return casulaties;
    }
    /**
     * 获取模型2的rj值  公式 lg/ln rj = param1+param2ln/lg烈度+param3ln/lg p
     */
    private BigDecimal getModel2Rj(RyswModel2 model2,Integer intensity,BigDecimal p){
        String symbol = model2.getSymbol();
        String symbol2 = model2.getSymbol2();
        String symbol3 = model2.getSymbol3();
        BigDecimal centerPart = BigDecimal.ZERO;
        BigDecimal postPart = BigDecimal.ZERO;
        BigDecimal rj = BigDecimal.ZERO;
        if ("ln".equals(symbol2)) {
            centerPart = model2.getParam2().multiply(BigDecimal.valueOf(Math.log(intensity)));
        } else if ("lg".equals(symbol2)) {
            centerPart = model2.getParam2().multiply(BigDecimal.valueOf(Math.log10(intensity)));
        }
        if ("ln".equals(symbol3)) {
            if(p.compareTo(BigDecimal.ZERO)>0){
                postPart = model2.getParam3().multiply(BigDecimal.valueOf(Math.log(p.doubleValue())));
            }
        } else if ("lg".equals(symbol3)) {
            if(p.compareTo(BigDecimal.ZERO)>0){
                postPart = model2.getParam3().multiply(BigDecimal.valueOf(Math.log10(p.doubleValue())));
            }
        }
        if ("ln".equals(symbol)) {
            rj = centerPart.subtract(model2.getParam1()).add(postPart);
            rj = BigDecimal.valueOf(Math.pow(Math.E, rj.doubleValue()));
        } else if ("lg".equals(symbol)) {
            rj = centerPart.subtract(model2.getParam1()).add(postPart);
            rj = BigDecimal.valueOf(Math.pow(10, rj.doubleValue()));
        }
        return rj;
    }
    /**
     * 获取模型1的rj值
     */
    private BigDecimal getModel1Rj(RyswModel1 model1,Integer intensity){
        BigDecimal rj = model1.getParam2().multiply(BigDecimal.valueOf(intensity)).subtract(model1.getParam1()).subtract((model1.getParam3().multiply(BigDecimal.valueOf(intensity * intensity))));
        String symbol = model1.getSymbol();
        if ("ln".equals(symbol)) {
            rj = BigDecimal.valueOf(Math.pow(Math.E, rj.doubleValue()));
        } else if ("lg".equals(symbol)) {
            rj = BigDecimal.valueOf(Math.pow(10, rj.doubleValue()));
        }
        return rj;
    }


    @DSTransactional
    private String evaluation(String dataSourceKey,BigDecimal timeRatio,int maxIntensity,Map<String, SettingSeismicInfluenceflied> intensityMap,
                              String earthQuakeId,Date influenceVersion) throws Exception {
        //先删除之前生成的相同影响场版本的数据
        LambdaQueryWrapper<Casulaties> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(Casulaties::getVersion,influenceVersion).eq(Casulaties::getEarthQuakeId,earthQuakeId);
        remove(lambdaQueryWrapper);
        StringBuilder builder = new StringBuilder();
        BigDecimal finalTimeRatio = timeRatio;
        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(()->{
            //相同线程是可以获取数据源的，但是异步不可以，需要重新设置
            System.out.println("线程1开始执行了");
            try{
                DynamicDataSourceContextHolder.push(dataSourceKey);
                //查询震中位置所在省的模型1和模型2的数据 模型数据使用的是震级所在的省的数据
                RyswModel1 model1 = ryswModelService1.getOne(null);
                RyswModel2 model2 = ryswModelService2.getOne(null);
//                List<RyswModel3Data> ryswModel3Data = ryswModel3DataService.getBaseMapper().selectList(null);
//                Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
                List<Casulaties> list = new ArrayList<>();
                //影响场最外圈默认跨省
                boolean flag = true;
                //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                for(int i=6;i<=maxIntensity;i++){
                    Map<Integer,Casulaties> casMap = new HashMap<>();
                    SettingSeismicInfluenceflied influence = intensityMap.get(i+"");
                    ToEvaluateVO.Influence influenceTemp = new  ToEvaluateVO.Influence();
                    influenceTemp.setGeom(influence.getGeomText());
                    String intensity = getIntensityMap().get(i);
                    if(ObjectUtils.isNotEmpty(influence)) {
                        //Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
                        //生成的影响场可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的人口数据数据，如果跨到的那个省的人口
                        //数据不存在我们计算所需要的数据就用国家的人口数据
                        List<DistrictBoundaryProvinceEntity> provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag,influenceTemp);
                        //provinces>1表示跨省了
                        double totalPopNum = 0.0;
                        for (DistrictBoundaryProvinceEntity province : provinces) {
                            //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                            DynamicDataSourceContextHolder.clear();
                            DynamicDataSourceContextHolder.push("province_"+province.getCode());
                            //每个烈度圈的人口数
                            double population =  getPopNum(province.getIntersectGeom());
                            totalPopNum+=population;
                        }
                        //ρ为人口密度，人口密度=该烈度下人口总数/该烈度下影响场面积 用于模型2计算
                        BigDecimal p = BigDecimal.ZERO;
                        if(influence.getArea()>0.001){
                            p = BigDecimal.valueOf(totalPopNum).divide(BigDecimal.valueOf(influence.getArea()),8, RoundingMode.HALF_DOWN);
                        }
                        //使用模型1计算人员伤亡
                        //获取死亡率RJ  RJ是i烈度下的死亡率
                        BigDecimal rj = getModel1Rj(model1, i);
                        //死亡人数
                        BigDecimal deadNum = BigDecimal.valueOf(totalPopNum).multiply(rj).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                        //受伤与死亡比例
                        BigDecimal ratio = model1.getRatio();
                        //受伤人数
                        BigDecimal injureNum = deadNum.multiply(ratio).setScale(0,RoundingMode.HALF_DOWN);;
                        Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum, injureNum, influenceVersion, 1);
                        getAndSetSum(1,casMap,casulaties1);
                        //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum,injureNum,influenceVersion,1));
                        //使用模型2计算人员伤亡
                        BigDecimal rj2 = getModel2Rj(model2, i,p);
                        //死亡人数
                        BigDecimal deadNum2 = BigDecimal.valueOf(totalPopNum).multiply(rj2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                        //受伤与死亡比例
                        BigDecimal ratio2 = model2.getRatio();
                        //受伤人数
                        BigDecimal injureNum2 = deadNum2.multiply(ratio2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);
                        Casulaties casulaties2 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum2, injureNum2, influenceVersion, 2);
                        //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum2,injureNum2,influenceVersion,2));
                        getAndSetSum(2,casMap,casulaties2);
                        if(provinces.size() == 1){
                            //不跨省  外圈不跨省那内圈肯定也不跨省就直接省去相交查询
                            flag = false;
                        }
                    }
                    Collection<Casulaties> values = casMap.values();
                    if(values.size()>0){
                        list.addAll(values);
                    }

//                    Map<Integer,Casulaties> casMap = new HashMap<>();
//                    SettingSeismicInfluenceflied influence = intensityMap.get(i+"");
//                    String intensity = getIntensityMap().get(i);
//                    if(ObjectUtils.isNotEmpty(influence)) {
//                        List<RyswModel3Data> ryswModel3Data = ryswModel3DataService.getDataByGeom(intensity,influence.getGeomText());
//                        if(ObjectUtils.isEmpty(ryswModel3Data) || ryswModel3Data.size()==0){
//                            continue;
//                        }
//                        //生成的影响场可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的人口数据数据，如果跨到的那个省的人口
//                        //数据不存在我们计算所需要的数据就用国家的人口数据
//                        ToEvaluateVO.Influence vo = new ToEvaluateVO.Influence();
//                        vo.setGeom(influence.getGeomText());
//                        vo.setArea(influence.getArea());
//                        provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag, vo);
//                        double totalPopNum = 0.0;
//                        //provinces>1表示跨省了
//                        for (DistrictBoundaryProvinceEntity province : provinces) {
//                            //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
//                            DynamicDataSourceContextHolder.clear();
//                            DynamicDataSourceContextHolder.push("province_"+province.getCode());
//                            //每个烈度圈的人口数
//                            double population =  getPopNum(province.getIntersectGeom());
//                            totalPopNum+=population;
//
//                        }
//                        //ρ为人口密度，人口密度=该烈度下人口总数/该烈度下影响场面积 用于模型2计算
//                        BigDecimal p = BigDecimal.ZERO;
//                        if(influence.getArea()>0.001){
//                            p = BigDecimal.valueOf(totalPopNum).divide(BigDecimal.valueOf(influence.getArea()),8, RoundingMode.HALF_DOWN);
//                        }
//
//
//                        //使用模型1计算人员伤亡
//                        //获取死亡率RJ  RJ是i烈度下的死亡率
//                        BigDecimal rj = getModel1Rj(model1, i);
//                        //死亡人数
//                        BigDecimal deadNum = BigDecimal.valueOf(totalPopNum).multiply(rj).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                        //受伤与死亡比例
//                        BigDecimal ratio = model1.getRatio();
//                        //受伤人数
//                        BigDecimal injureNum = deadNum.multiply(ratio).setScale(0,RoundingMode.HALF_DOWN);;
//                        Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum, injureNum, influenceVersion, 1);
//                        getAndSetSum(1,casMap,casulaties1);
//                        //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum,injureNum,influenceVersion,1));
//                        //使用模型2计算人员伤亡
//                        BigDecimal rj2 = getModel2Rj(model2, i,p);
//                        //死亡人数
//                        BigDecimal deadNum2 = BigDecimal.valueOf(totalPopNum).multiply(rj2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                        //受伤与死亡比例
//                        BigDecimal ratio2 = model2.getRatio();
//                        //受伤人数
//                        BigDecimal injureNum2 = deadNum2.multiply(ratio2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);
//                        Casulaties casulaties2 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deadNum2, injureNum2, influenceVersion, 2);
//                        //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum2,injureNum2,influenceVersion,2));
//                        getAndSetSum(2,casMap,casulaties2);
//                        //获取指定烈度的伤亡率
//                        RyswModel3Data ryswModel3Data1 = ryswModel3Data.get(0);;
//                        if(ObjectUtils.isNotEmpty(ryswModel3Data1)){
//                            BigDecimal deadRatio = ryswModel3Data1.getDeadRatio();
//                            BigDecimal deathNum3 = BigDecimal.valueOf(totalPopNum).multiply(deadRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                            BigDecimal injureRatio = ryswModel3Data1.getInjureRatio();
//                            BigDecimal injureNum3 = BigDecimal.valueOf(totalPopNum).multiply(injureRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                            //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deathNum3,injureNum3,influenceVersion,3));
//                            Casulaties casulaties3 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deathNum3, injureNum3, influenceVersion, 3);
//                            getAndSetSum(3,casMap,casulaties3);
//                        }
//
//                        if(provinces.size() == 1){
//                            //不跨省  外圈不跨省那内圈肯定也不跨省就直接省去相交查询
//                            flag = false;
//                        }
//                    }
//                    Collection<Casulaties> values = casMap.values();
//                    if(values.size()>0){
//                        list.addAll(values);
//                    }
                }
                if(list.size()>0){
                    //人员伤亡的计算结果需要保存在对应的专库中
                    DynamicDataSourceContextHolder.clear();
                    DynamicDataSourceContextHolder.push(dataSourceKey);
                    saveBatch(list);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                DynamicDataSourceContextHolder.clear();
                System.out.println("线程1执行完成");
            }
            return 1;
        },executor);
        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(()->{
            //相同线程是可以获取数据源的，但是异步不可以，需要重新设置
            System.out.println("线程2开始执行了");
            try{
                DynamicDataSourceContextHolder.push(dataSourceKey);
                //影响场最外圈默认跨省
                boolean flag = true;
                //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                List<Casulaties> casList = new ArrayList<>();
                for(int i=6;i<=maxIntensity;i++){
                    Map<Integer,Casulaties> casMap = new HashMap<>();
                    SettingSeismicInfluenceflied influence = intensityMap.get(i);
                    String intensity = getIntensityMap().get(i);
                    if(ObjectUtils.isNotEmpty(influence)) {
                        //Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
                        //获取指定烈度的伤亡率
                        List<RyswModel3Data> ryswModel3Data = ryswModel3DataService.getDataByGeom(intensity,influence.getGeom());
                        if(ObjectUtils.isEmpty(ryswModel3Data) || ryswModel3Data.size()==0){
                            continue;
                        }

                        BigDecimal totalDeathNum = BigDecimal.ZERO;
                        BigDecimal totalInjureNum = BigDecimal.ZERO;
                        for (RyswModel3Data ryswModel3Datum : ryswModel3Data) {
                            ToEvaluateVO.Influence influenceTemp = new ToEvaluateVO.Influence();
                            influenceTemp.setGeom(ryswModel3Datum.getGeomText());
                            //上传的伤亡率和烈度数据可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的人口数据数据，如果跨到的那个省的人口
                            //数据不存在我们计算所需要的数据就用国家的人口数据
                            List<DistrictBoundaryProvinceEntity> provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag,influenceTemp);
                            for (DistrictBoundaryProvinceEntity province : provinces) {
                                //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                                DynamicDataSourceContextHolder.clear();
                                DynamicDataSourceContextHolder.push("province_"+province.getCode());
                                //每个烈度圈的人口数
                                double population =  getPopNum(province.getIntersectGeom());
                                BigDecimal deadRatio = ryswModel3Datum.getDeadRatio();
                                BigDecimal deathNum3 = BigDecimal.valueOf(population).multiply(deadRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                totalDeathNum= totalDeathNum.add(deathNum3);
                                BigDecimal injureRatio = ryswModel3Datum.getInjureRatio();
                                BigDecimal injureNum3 = BigDecimal.valueOf(population).multiply(injureRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
                                totalInjureNum = totalInjureNum.add(injureNum3);

                            }
                        }
                        Casulaties casulaties3 = buildCasulaties(earthQuakeId, i, influence.getGeom(), totalDeathNum, totalInjureNum, influenceVersion, 3);
                        casList.add(casulaties3);
//                                if(ObjectUtils.isNotEmpty(ryswModel3Data1)){
//                                    BigDecimal deadRatio = ryswModel3Data1.getDeadRatio();
//                                    BigDecimal deathNum3 = BigDecimal.valueOf(totalPopNum).multiply(deadRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                                    BigDecimal injureRatio = ryswModel3Data1.getInjureRatio();
//                                    BigDecimal injureNum3 = BigDecimal.valueOf(totalPopNum).multiply(injureRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                                    //list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deathNum3,injureNum3,influenceVersion,3));
//                                    Casulaties casulaties3 = buildCasulaties(earthQuakeId, i, influence.getGeom(), deathNum3, injureNum3, influenceVersion, 3);
//                                    getAndSetSum(3,casMap,casulaties3);
//                                }

                    }
                }
                if(casList.size()>0){
                    //人员伤亡的计算结果需要保存在对应的专库中
                    DynamicDataSourceContextHolder.clear();
                    DynamicDataSourceContextHolder.push(dataSourceKey);
                    saveBatch(casList);
                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                DynamicDataSourceContextHolder.clear();
                System.out.println("线程2执行完成");
            }
            return 1;
        },executor);
        BigDecimal finalTimeRatio1 = timeRatio;
        CompletableFuture completableFuture3 = CompletableFuture.supplyAsync(()->{
            System.out.println("线程3开始执行了");
            try{
                DynamicDataSourceContextHolder.push(dataSourceKey);
                String currentProvince = dataSourceKey.replace("province_","");
                List<Casulaties> list1 = new ArrayList<>();
                //List<GridDestoryDetails> destoryList = new ArrayList<>();
                List<EconomyBuildingPriceEco> finalList = new ArrayList<>();
                //查询模型4的信息  模型数据使用的是震级所在的省的数据
                RyswModel4 model4 = ryswModelService4.getOne(null);
                //查询模型5 不同破坏程度下的伤亡率 模型数据使用的是震级所在的省的数据
                List<RyswModel5> model5List = ryswModelService5.list(null);
                Map<String, List<RyswModel5>> model5Map = new HashMap<>();
                if(ObjectUtils.isNotEmpty(model5List) && model5List.size()>0){
                    //按照破坏程度分组
                    model5Map = model5List.stream().collect(Collectors.groupingBy(RyswModel5::getDamageLevel));
                }
                List<DistrictBoundaryProvinceEntity> provinces = new ArrayList<>();
                //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
                List<InfluenceYsx> influenceYsxList = new ArrayList<>();
                //影响场最外圈默认跨省
                boolean flag = true;
                for(int i=6;i<=maxIntensity;i++){
                    SettingSeismicInfluenceflied influence = intensityMap.get(i+"");
                    if(ObjectUtils.isNotEmpty(influence)){
                        //根据影响场烈度的空间数据查询易损性数据 模型数据使用的是震级所在的省的数据
                        List<RyswModel4Data> ryswModel4DataList = ryswModel4DataService.getIntersectYsx(influence.getGeomText(), influence.getCode(),getIntensityMap().get(i));
                        //生成的影响场可能存在跨省的情况，如果跨省了，跨省的部分的计算使用的是跨到的那个省的数据，如果跨到的那个省的
                        //数据不存在我们计算所需要的数据就用国家的数据
                        //provinces>1表示跨省了
                        ToEvaluateVO.Influence vo = new ToEvaluateVO.Influence();
                        vo.setGeom(influence.getGeomText());
                        vo.setArea(influence.getArea());
                        provinces = getDistrictBoundaryProvinceEntities(dataSourceKey, flag, vo);
                        if(provinces.size() == 1){
                            //不跨省  外圈不跨省那内圈肯定也不跨省就直接省去相交查询
                            flag = false;
                        }
                        //影响场和易损性相交获取不同烈度下的易损性信息
                        if(ObjectUtils.isNotEmpty(ryswModel4DataList) && ryswModel4DataList.size()>0){
                            // 一个烈度圈可能与多个易损性数据相交7烈度的一半圈和一批易损性相交，另外半圈可能和另外的一批易损性数据相交
                            Map<String, List<RyswModel4Data>> pidMap = ryswModel4DataList.stream().collect(Collectors.groupingBy(RyswModel4Data::getIntersectGeom));
                            Iterator<Map.Entry<String, List<RyswModel4Data>>> iterator = pidMap.entrySet().iterator();
                            while (iterator.hasNext()){
                                Map.Entry<String, List<RyswModel4Data>> next = iterator.next();
                                List<RyswModel4Data> v = next.getValue();
                                //影响场烈度圈和易损性数据相交部分的空间数据
                                String geom = v.get(0).getIntersectGeom();
                                Map<Integer,Casulaties> casMap = new HashMap<>();
                                Map<Integer,Casulaties> casMap2 = new HashMap<>();

                                BigDecimal totalPopNum = BigDecimal.ZERO;
                                //用别省的人口和地震震中位置所在省的模型信息计算人员伤亡
                                for (DistrictBoundaryProvinceEntity province : provinces) {
                                    //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                                    DynamicDataSourceContextHolder.clear();
                                    DynamicDataSourceContextHolder.push("province_"+province.getCode());
                                    //人口p
                                    double popNum = 0;
                                    if(!flag){
                                        //不管跨没跨省只要是震中位置所在省，则需要使用影响场先和易损性相交geom，则使用相交的geom再和人口格网相交获取人口数
                                        popNum = getPopNum(geom);
                                    }else{
                                        //如果跨省了，那么查询跨省部分的空间数据与跨省人口格网的人口数据
                                        popNum = getPopNum(province.getIntersectGeom());
                                    }
                                    totalPopNum = totalPopNum.add(BigDecimal.valueOf(ObjectUtils.isEmpty(popNum)?0.0:popNum));

                                }
                                //计算模型4的算法  模型5需要模型4的易损性数据，需要在一个逻辑实现
                                Casulaties casulaties = mathModel4(earthQuakeId, influenceVersion, v, model4, i, geom,  finalList, totalPopNum.doubleValue(), null);
                                getAndSetSum(4,casMap,casulaties);
                                list1.addAll(casMap.values());
                                //计算人员伤亡模型5算法
                                //易损性存在不同的建筑物类别
                                BigDecimal deathNumTotal = BigDecimal.ZERO;
                                BigDecimal injureNumTotal = BigDecimal.ZERO;
                                for (RyswModel4Data ryswModel4Data : v) {
                                    BigDecimal basic = ryswModel4Data.getBasic();
                                    List<RyswModel5> ryswModel51 = model5Map.get("1");
                                    if(ObjectUtils.isNotEmpty(ryswModel51) && ryswModel51.size()>0){
                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                        BigDecimal deathNum = basic.multiply(ryswModel51.get(0).getDeadRatio()).multiply(totalPopNum);
                                        BigDecimal injureNum = basic.multiply(ryswModel51.get(0).getInjureRatio()).multiply(totalPopNum);
                                        deathNumTotal = deathNumTotal.add(deathNum);
                                        injureNumTotal = injureNumTotal.add(injureNum);
                                    }
                                    BigDecimal slight = ryswModel4Data.getSlight();
                                    List<RyswModel5> ryswModel52 = model5Map.get("2");
                                    if(ObjectUtils.isNotEmpty(ryswModel52) && ryswModel52.size()>0){
                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                        BigDecimal deathNum = slight.multiply(ryswModel52.get(0).getDeadRatio()).multiply(totalPopNum);
                                        BigDecimal injureNum = slight.multiply(ryswModel52.get(0).getInjureRatio()).multiply(totalPopNum);
                                        deathNumTotal = deathNumTotal.add(deathNum);
                                        injureNumTotal = injureNumTotal.add(injureNum);
                                    }
                                    BigDecimal mid = ryswModel4Data.getMid();
                                    List<RyswModel5> ryswModel53 = model5Map.get("3");
                                    if(ObjectUtils.isNotEmpty(ryswModel53) && ryswModel53.size()>0){
                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                        BigDecimal deathNum = mid.multiply(ryswModel53.get(0).getDeadRatio()).multiply(totalPopNum);
                                        BigDecimal injureNum = mid.multiply(ryswModel53.get(0).getInjureRatio()).multiply(totalPopNum);
                                        deathNumTotal = deathNumTotal.add(deathNum);
                                        injureNumTotal = injureNumTotal.add(injureNum);
                                    }
                                    BigDecimal serious = ryswModel4Data.getSerious();
                                    List<RyswModel5> ryswModel54 = model5Map.get("4");
                                    if(ObjectUtils.isNotEmpty(ryswModel54) && ryswModel54.size()>0){
                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                        BigDecimal deathNum = serious.multiply(ryswModel54.get(0).getDeadRatio()).multiply(totalPopNum);
                                        BigDecimal injureNum = serious.multiply(ryswModel54.get(0).getInjureRatio()).multiply(totalPopNum);
                                        deathNumTotal = deathNumTotal.add(deathNum);
                                        injureNumTotal = injureNumTotal.add(injureNum);
                                    }
                                    BigDecimal destory = ryswModel4Data.getDestory();
                                    List<RyswModel5> ryswModel55 = model5Map.get("5");
                                    if(ObjectUtils.isNotEmpty(ryswModel55) && ryswModel55.size()>0){
                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
                                        BigDecimal deathNum = destory.multiply(ryswModel55.get(0).getDeadRatio()).multiply(totalPopNum);
                                        BigDecimal injureNum = destory.multiply(ryswModel55.get(0).getInjureRatio()).multiply(totalPopNum);
                                        deathNumTotal = deathNumTotal.add(deathNum);
                                        injureNumTotal = injureNumTotal.add(injureNum);
                                    }
                                    //保存易损性中间结果用于其他算法的评估
                                    InfluenceYsx influenceYsx = new InfluenceYsx();
                                    //String provinceCode = dataSourceKey.indexOf("_")>0?dataSourceKey.split("_")[1]:dataSourceKey;
                                    influenceYsx.setId(UUID.randomUUID().toString().replace("-","")).setEarthQuakeId(earthQuakeId)
                                            .setInfluenceVersion(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(influenceVersion)).setIntensity(i+"").setGeom(geom).setPopNum(totalPopNum.doubleValue())
                                            .setStructureType(ryswModel4Data.getStructureType()).setMid(ryswModel4Data.getMid()).setSerious(ryswModel4Data.getSerious())
                                            .setDestory(ryswModel4Data.getDestory());
                                    influenceYsxList.add(influenceYsx);
                                }
                                deathNumTotal = deathNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
                                injureNumTotal = injureNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
                                Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, geom, deathNumTotal, injureNumTotal, influenceVersion, 5);
                                getAndSetSum(5,casMap2,casulaties1);
                                list1.addAll(casMap2.values());

//                                BigDecimal totalPopNum = BigDecimal.ZERO;
//                                //用别省的人口和地震震中位置所在省的模型信息计算人员伤亡
//                                for (DistrictBoundaryProvinceEntity province : provinces) {
//                                    //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
//                                    DynamicDataSourceContextHolder.clear();
//                                    DynamicDataSourceContextHolder.push("province_"+province.getCode());
//                                    //人口p
//                                    double popNum = 0;
//                                    if(!flag){
//                                        //不管跨没跨省只要是震中位置所在省，则需要使用影响场先和易损性相交geom，则使用相交的geom再和人口格网相交获取人口数
//                                        popNum = getPopNum(geom);
//                                    }else{
//                                        //如果跨省了，那么查询跨省部分的空间数据与跨省人口格网的人口数据
//                                        popNum = getPopNum(province.getIntersectGeom());
//                                    }
//                                    totalPopNum = totalPopNum.add(BigDecimal.valueOf(ObjectUtils.isEmpty(popNum)?0.0:popNum));
//                                    //计算模型4的算法  模型5需要模型4的易损性数据，需要在一个逻辑实现
//                                    Casulaties casulaties = mathModel4(earthQuakeId, influenceVersion, v, model4, i, geom, destoryList, popNum, builder);
//                                    getAndSetSum(4,casMap,casulaties);
//                                }
//                                list1.addAll(casMap.values());
//                                //计算人员伤亡模型5算法
//                                //易损性存在不同的建筑物类别
//                                BigDecimal deathNumTotal = BigDecimal.ZERO;
//                                BigDecimal injureNumTotal = BigDecimal.ZERO;
//                                for (RyswModel4Data ryswModel4Data : v) {
//                                    BigDecimal basic = ryswModel4Data.getBasic();
//                                    List<RyswModel5> ryswModel51 = model5Map.get("1");
//                                    if(ObjectUtils.isNotEmpty(ryswModel51) && ryswModel51.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = basic.multiply(ryswModel51.get(0).getDeadRatio()).multiply(totalPopNum);
//                                        BigDecimal injureNum = basic.multiply(ryswModel51.get(0).getInjureRatio()).multiply(totalPopNum);
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal slight = ryswModel4Data.getSlight();
//                                    List<RyswModel5> ryswModel52 = model5Map.get("2");
//                                    if(ObjectUtils.isNotEmpty(ryswModel52) && ryswModel52.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = slight.multiply(ryswModel52.get(0).getDeadRatio()).multiply(totalPopNum);
//                                        BigDecimal injureNum = slight.multiply(ryswModel52.get(0).getInjureRatio()).multiply(totalPopNum);
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal mid = ryswModel4Data.getMid();
//                                    List<RyswModel5> ryswModel53 = model5Map.get("3");
//                                    if(ObjectUtils.isNotEmpty(ryswModel53) && ryswModel53.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = mid.multiply(ryswModel53.get(0).getDeadRatio()).multiply(totalPopNum);
//                                        BigDecimal injureNum = mid.multiply(ryswModel53.get(0).getInjureRatio()).multiply(totalPopNum);
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal serious = ryswModel4Data.getSerious();
//                                    List<RyswModel5> ryswModel54 = model5Map.get("4");
//                                    if(ObjectUtils.isNotEmpty(ryswModel54) && ryswModel54.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = serious.multiply(ryswModel54.get(0).getDeadRatio()).multiply(totalPopNum);
//                                        BigDecimal injureNum = serious.multiply(ryswModel54.get(0).getInjureRatio()).multiply(totalPopNum);
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal destory = ryswModel4Data.getDestory();
//                                    List<RyswModel5> ryswModel55 = model5Map.get("5");
//                                    if(ObjectUtils.isNotEmpty(ryswModel55) && ryswModel55.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = destory.multiply(ryswModel55.get(0).getDeadRatio()).multiply(totalPopNum);
//                                        BigDecimal injureNum = destory.multiply(ryswModel55.get(0).getInjureRatio()).multiply(totalPopNum);
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    //保存易损性中间结果用于其他算法的评估
//                                    InfluenceYsx influenceYsx = new InfluenceYsx();
//                                    //String provinceCode = dataSourceKey.indexOf("_")>0?dataSourceKey.split("_")[1]:dataSourceKey;
//                                    influenceYsx.setId(UUID.randomUUID().toString().replace("-","")).setEarthQuakeId(earthQuakeId)
//                                            .setInfluenceVersion(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(influenceVersion)).setIntensity(i+"").setGeom(geom).setPopNum(totalPopNum.doubleValue())
//                                            .setStructureType(ryswModel4Data.getStructureType()).setMid(ryswModel4Data.getMid()).setSerious(ryswModel4Data.getSerious())
//                                            .setDestory(ryswModel4Data.getDestory());
//                                    influenceYsxList.add(influenceYsx);
//                                }
//                                deathNumTotal = deathNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
//                                injureNumTotal = injureNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
//                                Casulaties casulaties1 = buildCasulaties(earthQuakeId, i, geom, deathNumTotal, injureNumTotal, influenceVersion, 5);
//                                getAndSetSum(5,casMap2,casulaties1);
//                                list1.addAll(casMap2.values());
                            }
                        }else{
                            builder.append("烈度").append(i).append("没有获取到易损性数据").append("、");
                        }
                    }
                }
                //影响场跨省  如果查询的是跨省的那个需切换到跨省的那个数据源
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push(dataSourceKey);
                if(influenceYsxList.size()>0){
                    //记录影响场和易损性的相交后的信息用于后续的失去住所的评估计算
                    influenceYsxService.saveBatch(influenceYsxList);
                }
                if(list1.size()>0){
//                        LambdaQueryWrapper<Casulaties> lambdaQueryWrapper = new LambdaQueryWrapper<>();
//                        lambdaQueryWrapper.eq(Casulaties::getEarthQuakeId,earthQuakeId).eq(Casulaties::getVersion,influenceVersion);
//                        remove(lambdaQueryWrapper);
                    saveBatch(list1);
                }
                //用于经济损失建筑物结构经济损失
//                if(destoryList.size()>0){
////                        LambdaQueryWrapper<GridDestoryDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
////                        lambdaQueryWrapper.eq(GridDestoryDetails::getEarthQuakeId,earthQuakeId).eq(GridDestoryDetails::getInfluenceVersion,influenceVersion);
////                        gridDestoryDetailsService.remove(lambdaQueryWrapper);
//                    gridDestoryDetailsService.saveBatch(destoryList);
//                }
//                if(finalList.size()>0){
//                    economyBuildingPriceEcoService.saveBatch(finalList);
//                }
            }catch (Exception e){
                e.printStackTrace();
            }finally {
                DynamicDataSourceContextHolder.clear();
            }

            System.out.println("线程3执行完成");
            return 2;
        },executor);
        CompletableFuture.allOf(completableFuture1,completableFuture2,completableFuture3).get();
        System.out.println("执行完毕");
        return builder.toString();
    }
//    private String evaluation(String dataSourceKey,BigDecimal timeRatio,int maxIntensity,Map<String, SettingSeismicInfluenceflied> intensityMap,
//                            String earthQuakeId,Date influenceVersion) throws Exception {
//        StringBuilder builder = new StringBuilder();
//        BigDecimal finalTimeRatio = timeRatio;
//        CompletableFuture completableFuture1 = CompletableFuture.supplyAsync(()->{
//            //相同线程是可以获取数据源的，但是异步不可以，需要重新设置
//            System.out.println("线程1开始执行了");
//            try{
//                DynamicDataSourceContextHolder.push(dataSourceKey);
//                // 开始使用人员伤亡模型1计算人员伤亡数据
//                RyswModel1 model1 = ryswModelService1.getOne(null);
//                RyswModel2 model2 = ryswModelService2.getOne(null);
//                List<Casulaties> list = new ArrayList<>();
//                //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
//                for(int i=6;i<=maxIntensity;i++){
//                    SettingSeismicInfluenceflied influence = intensityMap.get(i+"");
//                    if(ObjectUtils.isNotEmpty(influence)){
//                        //影响场和人口格网相交取值
//                        List<DataPop> dataPop = null;
//                        try{
//                            dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(), influence.getCode());
//                        }catch (UncategorizedSQLException e){
//                            if("4490".equals(influence.getCode())){
//                                influence.setCode("4326");
//                                dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(),influence.getCode());
//                            }else if("4326".equals(influence.getCode())){
//                                influence.setCode("4490");
//                                dataPop = popService.getBaseMapper().getByGeom(influence.getGeomText(), influence.getCode());
//                            }
//                        }
//                        //每个烈度圈的人口数
//                        if(dataPop==null){
//                            dataPop = new ArrayList<>();
//                            DataPop pop = new DataPop();
//                            pop.setPopulation(0.0);
//                            dataPop.add(pop);
//                        }
//                        Double population =  dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
//                        //ρ为人口密度，人口密度=该烈度下人口总数/该烈度下影响场面积 用于模型2计算
//                        BigDecimal p = BigDecimal.ZERO;
//                        if(influence.getArea()!=0){
//                            p = BigDecimal.valueOf(population).divide(BigDecimal.valueOf(influence.getArea()),8, RoundingMode.HALF_DOWN);
//                        }
//
//                        if(ObjectUtils.isNotEmpty(p)){
//                            //使用模型1计算人员伤亡
//                            //获取死亡率RJ  RJ是i烈度下的死亡率
//                            BigDecimal rj = getModel1Rj(model1, i);
//                            //死亡人数
//                            BigDecimal deadNum = BigDecimal.valueOf(population).multiply(rj).setScale(0,RoundingMode.HALF_DOWN);;
//                            //受伤与死亡比例
//                            BigDecimal ratio = model1.getRatio();
//                            //受伤人数
//                            BigDecimal injureNum = deadNum.multiply(ratio).setScale(0,RoundingMode.HALF_DOWN);;
//                            list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum,injureNum,influenceVersion,1));
//                            //使用模型2计算人员伤亡
//                            BigDecimal rj2 = getModel2Rj(model2, i,p);
//                            //死亡人数
//                            BigDecimal deadNum2 = BigDecimal.valueOf(population).multiply(rj2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);
//                            //受伤与死亡比例
//                            BigDecimal ratio2 = model2.getRatio();
//                            //受伤人数
//                            BigDecimal injureNum2 = deadNum2.multiply(ratio2).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);
//                            list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deadNum2,injureNum2,influenceVersion,2));
//                            //计算模型3的人员伤亡数据
//                            List<RyswModel3Data> ryswModel3Data = ryswModel3DataService.getBaseMapper().selectList(null);
//                            Map<String, RyswModel3Data> influenceMap = ryswModel3Data.stream().collect(Collectors.toMap(RyswModel3Data::getIntensity, Function.identity()));
//                            //获取指定烈度的伤亡率
//                            RyswModel3Data ryswModel3Data1 = influenceMap.get(getIntensityMap().get(i));
//                            if(ObjectUtils.isNotEmpty(ryswModel3Data1)){
//                                BigDecimal deadRatio = ryswModel3Data1.getDeadRatio();
//                                BigDecimal deathNum3 = BigDecimal.valueOf(population).multiply(deadRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                                BigDecimal injureRatio = ryswModel3Data1.getInjureRatio();
//                                BigDecimal injureNum3 = BigDecimal.valueOf(population).multiply(injureRatio).multiply(finalTimeRatio).setScale(0,RoundingMode.HALF_DOWN);;
//                                list.add(buildCasulaties(earthQuakeId,i,influence.getGeom(),deathNum3,injureNum3,influenceVersion,3));
//                            }
//                        }
//                    }
//                }
//                if(list.size()>0){
//                    saveBatch(list);
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }finally {
//                DynamicDataSourceContextHolder.clear();
//                System.out.println("线程1执行完成");
//            }
//            return 1;
//        },executor);
//        BigDecimal finalTimeRatio1 = timeRatio;
//        CompletableFuture completableFuture2 = CompletableFuture.supplyAsync(()->{
//            System.out.println("线程2开始执行了");
//            try{
//                DynamicDataSourceContextHolder.push(dataSourceKey);
//                List<Casulaties> list1 = new ArrayList<>();
//                List<GridDestoryDetails> destoryList = new ArrayList<>();
//                RyswModel4 model4 = ryswModelService4.getOne(null);
//                List<RyswModel5> model5List = ryswModelService5.list(null);
//                Map<String, List<RyswModel5>> model5Map = new HashMap<>();
//                if(ObjectUtils.isNotEmpty(model5List) && model5List.size()>0){
//                    model5Map = model5List.stream().collect(Collectors.groupingBy(RyswModel5::getDamageLevel));
//                }
//                //影响场的计算从烈度6开始，一直到实际影响场的最大烈度
//                List<InfluenceYsx> influenceYsxList = new ArrayList<>();
//                for(int i=6;i<=maxIntensity;i++){
//                    SettingSeismicInfluenceflied influence = intensityMap.get(i+"");
//                    if(ObjectUtils.isNotEmpty(influence)){
//                        //影响场和易损性相交获取不同烈度下的易损性信息
//                        // 一个烈度圈可能与多个易损性数据相交7烈度的一半圈和一批易损性相交，另外半圈可能和另外的一批易损性数据相交
//                        List<RyswModel4Data> ryswModel4DataList = ryswModel4DataService.getIntersectYsx(influence.getGeomText(), influence.getCode(),getIntensityMap().get(i));
//                        if(ObjectUtils.isNotEmpty(ryswModel4DataList) && ryswModel4DataList.size()>0){
//                            Map<String, List<RyswModel4Data>> pidMap = ryswModel4DataList.stream().collect(Collectors.groupingBy(RyswModel4Data::getIntersectGeom));
//                            Iterator<Map.Entry<String, List<RyswModel4Data>>> iterator = pidMap.entrySet().iterator();
//                            while (iterator.hasNext()){
//                                Map.Entry<String, List<RyswModel4Data>> next = iterator.next();
//                                List<RyswModel4Data> v = next.getValue();
//                                //人口p
//                                String geom = v.get(0).getIntersectGeom();
//                                String code = v.get(0).getCode();
//                                List<DataPop> dataPop =  popService.getBaseMapper().getByGeom(geom, "4490");
//                                if(ObjectUtils.isEmpty(dataPop)){
//                                    dataPop = new ArrayList<>();
//                                    DataPop pop = new DataPop();
//                                    pop.setPopulation(0.0);
//                                    dataPop.add(pop);
//                                }
//                                double popNum = dataPop.stream().mapToDouble(DataPop::getPopulation).sum();
//                                SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//                                for (RyswModel4Data ryswModel4Data : v) {
//                                    InfluenceYsx influenceYsx = new InfluenceYsx();
//                                    influenceYsx.setId(UUID.randomUUID().toString().replace("-","")).setEarthQuakeId(earthQuakeId)
//                                            .setInfluenceVersion(simpleDateFormat.format(influenceVersion)).setIntensity(i+"").setGeom(geom).setPopNum(popNum)
//                                            .setStructureType(ryswModel4Data.getStructureType()).setMid(ryswModel4Data.getMid()).setSerious(ryswModel4Data.getSerious())
//                                            .setDestory(ryswModel4Data.getDestory());
//                                    influenceYsxList.add(influenceYsx);
//                                }
//                                //计算模型4的算法  模型5需要模型4的易损性数据，需要在一个逻辑实现
//                                mathModel4(earthQuakeId,influenceVersion,v,model4,i,geom,list1,destoryList,popNum,builder);
//                                //易损性存在不同的建筑物类别
//                                BigDecimal deathNumTotal = BigDecimal.ZERO;
//                                BigDecimal injureNumTotal = BigDecimal.ZERO;
//                                for (RyswModel4Data ryswModel4Data : v) {
//                                    BigDecimal basic = ryswModel4Data.getBasic();
//                                    List<RyswModel5> ryswModel51 = model5Map.get("1");
//                                    if(ObjectUtils.isNotEmpty(ryswModel51) && ryswModel51.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = basic.multiply(ryswModel51.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        BigDecimal injureNum = basic.multiply(ryswModel51.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal slight = ryswModel4Data.getSlight();
//                                    List<RyswModel5> ryswModel52 = model5Map.get("2");
//                                    if(ObjectUtils.isNotEmpty(ryswModel52) && ryswModel52.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = slight.multiply(ryswModel52.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        BigDecimal injureNum = slight.multiply(ryswModel52.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal mid = ryswModel4Data.getMid();
//                                    List<RyswModel5> ryswModel53 = model5Map.get("3");
//                                    if(ObjectUtils.isNotEmpty(ryswModel53) && ryswModel53.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = mid.multiply(ryswModel53.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        BigDecimal injureNum = mid.multiply(ryswModel53.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal serious = ryswModel4Data.getSerious();
//                                    List<RyswModel5> ryswModel54 = model5Map.get("4");
//                                    if(ObjectUtils.isNotEmpty(ryswModel54) && ryswModel54.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = serious.multiply(ryswModel54.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        BigDecimal injureNum = serious.multiply(ryswModel54.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                    BigDecimal destory = ryswModel4Data.getDestory();
//                                    List<RyswModel5> ryswModel55 = model5Map.get("5");
//                                    if(ObjectUtils.isNotEmpty(ryswModel55) && ryswModel55.size()>0){
//                                        //各烈度下各破坏程度的易损性值*对应破坏程度的死亡率R，受伤率W.再乘以对应区域的人口总数
//                                        BigDecimal deathNum = destory.multiply(ryswModel55.get(0).getDeadRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        BigDecimal injureNum = destory.multiply(ryswModel55.get(0).getInjureRatio()).multiply(BigDecimal.valueOf(popNum));
//                                        deathNumTotal = deathNumTotal.add(deathNum);
//                                        injureNumTotal = injureNumTotal.add(injureNum);
//                                    }
//                                }
//                                deathNumTotal = deathNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
//                                injureNumTotal = injureNumTotal.multiply(finalTimeRatio1).setScale(0,RoundingMode.HALF_DOWN);
//                                list1.add(buildCasulaties(earthQuakeId,i,geom,deathNumTotal,injureNumTotal,influenceVersion,5));
//                            }
//                        }else{
//                            builder.append("烈度").append(i).append("没有获取到易损性数据").append("、");
//                        }
//                    }
//                }
//                if(influenceYsxList.size()>0){
//                    //记录影响场和易损性的相交后的信息用于后续的失去住所的评估计算
//                    influenceYsxService.saveBatch(influenceYsxList);
//                }
//                if(list1.size()>0){
////                        LambdaQueryWrapper<Casulaties> lambdaQueryWrapper = new LambdaQueryWrapper<>();
////                        lambdaQueryWrapper.eq(Casulaties::getEarthQuakeId,earthQuakeId).eq(Casulaties::getVersion,influenceVersion);
////                        remove(lambdaQueryWrapper);
//                    saveBatch(list1);
//                }
//                //用于经济损失建筑物结构经济损失
//                if(destoryList.size()>0){
////                        LambdaQueryWrapper<GridDestoryDetails> lambdaQueryWrapper = new LambdaQueryWrapper<>();
////                        lambdaQueryWrapper.eq(GridDestoryDetails::getEarthQuakeId,earthQuakeId).eq(GridDestoryDetails::getInfluenceVersion,influenceVersion);
////                        gridDestoryDetailsService.remove(lambdaQueryWrapper);
//                    gridDestoryDetailsService.saveBatch(destoryList);
//                }
//            }catch (Exception e){
//                e.printStackTrace();
//            }finally {
//                DynamicDataSourceContextHolder.clear();
//            }
//
//            System.out.println("线程2执行完成");
//            return 2;
//        },executor);
//        CompletableFuture.allOf(completableFuture1,completableFuture2).get();
//        System.out.println("执行完毕");
//        return builder.toString();
//    }
    @Override
    public String rebuild(String earthQuakeId, String type, String version, HttpServletRequest request) throws Exception {
        StringBuilder resultMsg = new StringBuilder("评估未完成,");
        String code = request.getHeader("divisionCode");
        String divisionCode = "";
        if(StringUtils.isBlank(code)){
            divisionCode = "root";
        }else{
            divisionCode = code.split("_")[0];
        }

        try{
            //查询地震信息
            if("2".equals(type) || "3".equals(type)){
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }else{
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.push("slave");
            }
            EarthQuake earthQuake = earthQuakeInfluenceService.getById(earthQuakeId);

            if("1".equals(type) || "4".equals(type)){
                //正式和自动的地震默认查询公共库，但是测试和演练的地震去各自专用库中查询地震信息
                DynamicDataSourceContextHolder.clear();
                DynamicDataSourceContextHolder.push("province_"+divisionCode);
            }
            //获取影响场信息
            List<SettingSeismicInfluenceflied> list = settingInfluenceMapper.selectInfluence(earthQuakeId, version);
            if(ObjectUtils.isNotEmpty(list) && list.size()>0){
                String geomText = "POINT ("+earthQuake.getLongitude()+" "+earthQuake.getLatitude()+")";
                //给图件生成规则发送消息
                influenceService.sendMsgToMapRule(list,earthQuake,DynamicDataSourceContextHolder.peek(),geomText);
                SettingSeismicInfluenceflied influenceflied = list.stream()
                        .max(Comparator.comparing(SettingSeismicInfluenceflied::getDzIntensity)).get();
                int maxIntensity = Integer.parseInt(influenceflied.getDzIntensity());
                BigDecimal timeRatio = getTimeRatio(maxIntensity, earthQuake.getEarthquakeTime());
                if(timeRatio==null){
                    timeRatio = BigDecimal.ONE;
                }
                Map<String, SettingSeismicInfluenceflied> intensityMap = list.stream().collect(Collectors.toMap(SettingSeismicInfluenceflied::getDzIntensity, Function.identity()));
                //评估人员伤亡
                try{
                    String msg = this.evaluation(DynamicDataSourceContextHolder.peek(),timeRatio,maxIntensity,intensityMap,earthQuakeId,DateUtil.parse(version,"yyyy-MM-dd HH:mm:ss"));
                    resultMsg.append(msg);
                }catch (Exception e){
                    resultMsg.append("人员伤亡评估失败");
                }
                //评估经济损失
                try{
                    economyEvaluateService.evaluation(DynamicDataSourceContextHolder.peek(),timeRatio,maxIntensity,intensityMap,earthQuakeId,DateUtil.parse(version,"yyyy-MM-dd HH:mm:ss"),list);
                }catch (Exception e){
                    resultMsg.append("经济损失评估失败");
                }
                sendMsgToReport(earthQuakeId,Integer.parseInt(type),DynamicDataSourceContextHolder.peek(),earthQuake.getIsPublish(),version);
                //评估失去住所人数
                try{
                    lossHouseService.evaluation(earthQuakeId,version);
                }catch (Exception e){
                    resultMsg.append("失去住所人数评估失败");
                }
//                //地震滑坡
                try{
                    LandslideParam riskLevel = new LandslideParam();
                    riskLevel.setEarthQuakeId(earthQuake.getId()+"");
                    riskLevel.setInfluenceVersion(version);
                    riskLevel.setDataSourceKey(DynamicDataSourceContextHolder.peek());
                    String msg = landslideRiskService.calculateLandslideRiskManual(riskLevel);
                    resultMsg.append(msg);
                }catch (Exception e){
                    resultMsg.append("地震滑坡评估失败");
                }
            }else{
                resultMsg.append("没有获取到影响场信息。");
            }
        }catch (Exception e){
             e.printStackTrace();
        }finally {
            DynamicDataSourceContextHolder.clear();
        }
        if("评估未完成,".equals(resultMsg.toString())){
            return "";
        }else{
            return resultMsg.toString();
        }
    }

    private void sendMsgToReport(String id,Integer earthQuakeType,String dataSourceKey,Boolean publish,String version)  {
        Map<String,Object> toReportMap = new HashMap<>();
        toReportMap.put("earthQuakeId",id);
        toReportMap.put("earthQuakeType",earthQuakeType);
        toReportMap.put("dataSourceKey",dataSourceKey);
        toReportMap.put("publish",publish);
        toReportMap.put("influenceVersion",version);
        //1 是自动触发生成的  2是手动重新计算的影响场
        toReportMap.put("influenceType","2");
        String status = "成功";
        try{
            rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,toReportMap);
            log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toReportMap));
        }catch (Exception e){
            boolean flag = false;
            for (int i=0;i<failedRetry;i++) {
                try{
                    Thread.sleep(500);
                    rabbitTemplate.convertAndSend(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,toReportMap);
                    flag = true;
                    log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 成功。>> 参数:"+JSON.toJSONString(toReportMap));
                    break;
                }catch (Exception ignored){
                }
            }
            if(!flag){
                status = "失败";
                log.error("地震id"+id+"-- 影响场给报告发送消息"+"|| 失败。>> 参数:"+JSON.toJSONString(toReportMap));
            }
        }finally {
            try{
                LinkedHashMap<String, Object> content = JSON.parseObject(JSON.toJSONString(toReportMap), new TypeReference<LinkedHashMap<String, Object>>() {
                });
                messageLogService.createAndSaveMessageLog(QueueConfig.EXCHANGE_INFLUENCE,QueueConfig.KEY_INFLUENCE_TO_REPORT,status, content,"影响场发送消息给报告","Map");
            }catch (Exception e){
                //消息发送情况的保存即使失败了也不能影响到影响场数据的保存 因为消息失败了也不会补偿发送所以偶尔保存失败也不会有很大的影响
                e.printStackTrace();
            }
        }
    }
}
